package org.sfx.control

import org.sfx.rich.Enrich._

import javafx.scene.control.Control
import javafx.collections.ObservableList
import javafx.collections.FXCollections
import javafx.beans.property.ObjectProperty
import javafx.scene.control.SingleSelectionModel
import javafx.beans.property.SimpleObjectProperty
import javafx.collections.ListChangeListener

import scala.collection.JavaConverters._

class TabPane extends Control {
  val tabs: ObservableList[Tab] = FXCollections.observableArrayList()
  val selectionModel: ObjectProperty[SingleSelectionModel[Tab]] =
    new SimpleObjectProperty(this, "selectionModel", new TabPaneSelectionModel())

  this.setSkin(new TabPaneSkin(this))
  
  this.tabs.addChangeListener { change =>
    while (change.next) {
      for (myTab <- change.getRemoved.asScala) {
        if (!TabPane.this.tabs.contains(myTab)) {
          myTab.tabPane = null
        }
      }
 
      for (myTab <- change.getAddedSubList.asScala) {
        myTab.tabPane = TabPane.this
      }
    }
  }

  
  class TabPaneSelectionModel extends SingleSelectionModel[Tab] {
    TabPane.this.tabs.addChangeListener { change =>
      if (TabPane.this.tabs.isEmpty) {
        TabPaneSelectionModel.this.clearSelection()
      } else {
        while (change.next()) {
          if (change.getRemoved.asScala.dropWhile(!_.selected).size > 0) {
            if (change.getFrom < TabPane.this.tabs.size) {
              TabPaneSelectionModel.this.select(change.getFrom)
            } else {
              TabPaneSelectionModel.this.selectLast()
            }
          }
        }
        
        if (TabPaneSelectionModel.this.getSelectedIndex == -1 && TabPane.this.tabs.size > 0) {
          TabPaneSelectionModel.this.selectFirst()
        }
      }
    }
 
    override def select(index: Int): Unit = {
      if (index < 0 || index >= getItemCount) {
        // Ignore if index invalid.
        return
      }
 
      if (this.getSelectedIndex != -1 && getSelectedIndex < TabPane.this.tabs.size) {
        // The current selected tab is valid.  Mark last selected tab as not selected
        TabPane.this.tabs.get(getSelectedIndex).selected = false
      }
      
      // Select tab for given index
      setSelectedIndex(index)
      setSelectedItem(getModelItem(index))
      TabPane.this.tabs.get(getSelectedIndex).selected = true
    }
 
    protected def getModelItem(index: Int): Tab = {
      if (index < 0 || index >= TabPane.this.tabs.size) {
        return null
      }
      
      return TabPane.this.tabs.get(index)
    }
 
    protected def getItemCount(): Int = TabPane.this.tabs.size
  }
}
